-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove inline Javascript, part I #9513
base: master
Are you sure you want to change the base?
Conversation
@alecpl I don't know yet why the tests fail, will have a look at that on monday. But if you have the time maybe you can already have a look if you (roughly) agree? |
c8efaeb
to
abe9212
Compare
1bce625
to
965e50e
Compare
@alecpl Could you have a look at this, please? I'll go forward and work on extracting inline event handlers, but I'd like to know as early as possible about vetos from your side. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some preliminary comments. Overall not bad.
} | ||
} catch (e) { } | ||
</script> | ||
<script src="./dark-mode.js"></script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably would be better to move to ui.js.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then we lose the conditional in layout.html: https://github.com/pabzm/roundcubemail/blob/965e50ea084d799bc0b337e542ba32054dec582e/skins/elastic/templates/includes/layout.html#L31
Do you want to drop that?
Also using us.js
as dependency in watermark.html
doesn't look good, I think.
Even if you want to reduce the amount of JS-files I'd argue that this code snippet is really well suited for its own file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Less files is better. If the options are load dark-mode.js v. load ui.js, I choose ui.js (it will be already cached by the browser).
if (!empty($this->script_files['foot'])) { | ||
$page_footer .= array_reduce((array) $this->script_files['foot'], $merge_script_files); | ||
} | ||
$page_footer .= html::div(['id' => 'js-data', 'style' => 'display: none', 'hidden' => true], $this->get_js_commands()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to encode the div content here. E.g. to not contain <
and >
, etc. Then I think we should be able to do .text()
on the client side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather go with the current code, because it's safe enough (JSON-encoded), and encoding and then decoding everything adds a (maybe small but still) performance weight. Also, it works, why change it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While doing the requested changes the data handling broke again, so I decided to use a data-attribute instead. That works for all cases.
a2b0156
to
e8036cf
Compare
I rebased onto the latest |
* @param string $script JS code snippet | ||
* @param string $position Target position [head|head_top|foot|docready] | ||
*/ | ||
public function add_script($script, $position = 'head') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of removing the API we should consider using the nonce
for these. It would make the plugin developers life easier. However, there will be problem with execution order, I suppose, so I'm not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to not offer that option, because it's cleaner without it, and I guess most plugin authors wouldn't bother to clean up their code if it still works, which factually will degrade the CSP-related security of most Roundcube installations.
As you see in this branch, converting code to use external script files isn't really hard. It's just some chores to modernise ones code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also the potential problems with code order you mentioned might well result in a steady stream of issues, which we would need to take care of – that's a work load I would very much like to avoid, especially since Roundcube only loses security advancements from it.
Another case to figure out is |
This isn't meant to completely remove all inline-JS at once, that would be too big a change, I figured. It's only the first part, as the title says. I already made some progress on further changes to take care of event-handlers (which led to #9544), but I'd like this to be merged before I open another PR to avoid overload. |
Well, this is one big BC break. I'd rather see it completed before we make the decision to merge. There will be no return. |
This allows to call it on specific elements only, e.g. after they've been inserted late to the DOM.
There's no apparent reason for them to be static, and no explanation, but as instance methods they are directly callable from the de-inlined event-handlers and we save some helper methods, which is good.
This make it easier for the calling code.
Have to repeat attaching event handlers after a clone().
This allows to strip 'unsafe-eval' from the CSP.
innerHTML requires 'unsafe-eval' in the CSP, while innerText doesn't.
If the last argument to a data-on* attribute is an object (associative array in PHP), it is used as options, which allow to specify if preventDefault() should be called on the event. This is relevant for some parts of the code and got lost in previous changes.
72cfd49
to
fedc7d2
Compare
(Rebased to latest of "master") |
@alecpl I would really appreciate if you would take the time to reply again on this topic. Just getting the ball dropped is a pretty frustrating collaboration experience. |
As part of #9508 here's a change that removes
add_script()
and transportsjs_commands
in JSON, which then gets interpreted as callbacks to call with given arguments, instead ofeval
ing strings.This does not tackle the many inline event handlers, in order to keep it manageable.